import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;

import replay.SerialPlayField;
import replay.StateTable;

import com.golden.gamedev.*;
import com.golden.gamedev.object.*;
import com.golden.gamedev.object.collision.*;
import com.golden.gamedev.util.ImageUtil;

public abstract class AbstractLevel extends GameObject {
	protected int ID;
	protected int cannonFrame;
	protected BufferedImage cannonImage;
	protected double cannonWidth;
	protected double cannonHeight;
	protected double projectileAngle;
	protected boolean firedBall;
	protected Sprite cannon;
	protected SpriteGroup projectile;
	protected SpriteGroup obstacles;
	protected SpriteGroup enemy;
	protected SpriteGroup goal;
	protected Background background;
	protected CollisionGroup collisionType;
	protected CollisionGroup collisionOver;
	protected PlayField currentPlayField;
	protected boolean isResume;

	protected StateTable st;

	// protected PlayField currentPlayField;
	public AbstractLevel(GameEngine engine, boolean resume) {
		super(engine);
		isResume = resume;
	}

	@Override
	public void initResources() {
		if (isResume) {
			Resume resume = new Resume();
			currentPlayField = resume.resumeGame("default");
			enemy = currentPlayField.getGroup("enemies");
			projectile =currentPlayField.getGroup("projectile");
			obstacles = currentPlayField.getGroup("obstacles");
			goal = currentPlayField.getGroup("Goal");
			System.out.println("im here");
			/*for(Sprite s: currentPlayField.getExtraGroup().getSprites()){
				if(s.getID() == 10 && s!= null)
					cannon = s;
			}*/
		} else {
			initLevel();
			st = new StateTable();
			//System.out.println(ID);
			projectileAngle = 50;
			cannonFrame = 0;
			projectile = currentPlayField
					.addGroup(new SpriteGroup("projectile"));
			goal = currentPlayField.addGroup(new SpriteGroup("Goal"));
			cannonImage = getImage("images/cannon.png");
			cannon = new Sprite(cannonImage, 0, 200);
			cannon.setID(10);
			currentPlayField.add(cannon);
			cannonWidth = cannon.getWidth();
			cannonHeight = cannon.getHeight();
			cannon.setBackground(background);
			BufferedImage ball = getImage("images/cannonball.png");
			projectile.add(new Sprite(ball, 1, 200));
			projectile.setBackground(background);
			firedBall = false;
			goal.add(new Sprite(getImage("images/smallTarget.png"), 590, 200));
			goal.setBackground(background);

			// all collisions
			currentPlayField.addCollisionGroup(enemy, null, new BoundCollision(
					65, 0, background.getWidth() - 65, background.getHeight()));
			currentPlayField.addCollisionGroup(projectile, null,
					new BallHitBounds(background));
			currentPlayField.addCollisionGroup(projectile, obstacles,
					new BounceCollisions());
			currentPlayField.addCollisionGroup(enemy, obstacles,
					new BounceCollisions());
			currentPlayField.addCollisionGroup(enemy, goal,
					new BounceCollisions());
			currentPlayField.addCollisionGroup(projectile, goal,
					new LoseOrWinCollision());
			currentPlayField.addCollisionGroup(projectile, enemy,
					new LoseOrWinCollision());
		}
	}

	abstract public void initLevel();

	/*
	 * @Override public void render(Graphics2D g) { currentPlayField.render(g);
	 * }
	 */

	@Override
	public void update(long elapsedTime) {
		currentPlayField.update(elapsedTime);

		if (!(enemy.getInactiveSprite() == null)) {
			this.parent.nextGameID = (4);
			((MyBallGame) this.parent).setPrevGameID(ID);
			((MyBallGame) this.parent).setPrevGame(this);
			this.finish();
		}
		if (!(goal.getInactiveSprite() == null)) {
			this.parent.nextGameID = (this.parent.getCurrentGameID() + 1);
			this.finish();
		} else if (!(projectile.getInactiveSprite() == null)) {
			this.parent.nextGameID = (4);
			((MyBallGame) this.parent).setPrevGameID(ID);
			((MyBallGame) this.parent).setPrevGame(this);
			this.finish();
		}

		if (firedBall == false) {
			if (keyDown(KeyEvent.VK_DOWN)) {
				projectileAngle = ((int) elapsedTime / 5) * cannonFrame + 50;
				System.out.println(projectileAngle);
				cannon.setImage(ImageUtil.rotate(cannonImage,
						((int) elapsedTime / 5) * cannonFrame));
				cannon.setBackground(background);
				cannonFrame++;
			} else if (keyDown(KeyEvent.VK_UP)) {
				cannonFrame--;
				projectileAngle = ((int) elapsedTime / 5) * cannonFrame + 50;
				cannon.setImage(ImageUtil.rotate(cannonImage,
						((int) elapsedTime / 5) * cannonFrame));
				cannon.setBackground(background);
			}
		}

		if (keyPressed(KeyEvent.VK_SPACE) && !firedBall) {
			firedBall = true;
			projectile.getSprites()[0].setActive(true);
			projectile.getSprites()[0].setMovement(0.3, projectileAngle);
		}

		if (keyPressed(KeyEvent.VK_ESCAPE)) {
			parent.nextGameID = 0;
			finish();
		}

		if (!goal.isActive()) {
			this.parent.nextGameID = this.parent.getCurrentGameID() + 1;
		}

		st.record(currentPlayField);

	}

	/*
	 * protected BufferedImage rotateImage(BufferedImage image, double angle) {
	 * BufferedImage rotatedImage = image; AffineTransform at = new
	 * AffineTransform(); at.rotate(angle, cannonWidth/2,
	 * cannonHeight/2);//rotatedImage.getWidth(null)/2,
	 * rotatedImage.getHeight(null)/2); AffineTransformOp op = new
	 * AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR); rotatedImage =
	 * op.filter(rotatedImage, null); return rotatedImage; }
	 */
	@Override
	public void render(Graphics2D g) {
		currentPlayField.render(g);
	}

	public StateTable getTable() {
		return st;
	}
}
